package store.lunangangster.engine.impl.bpmn.behavior;

import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import store.lunangangster.bpmn.model.InclusiveGateway;
import store.lunangangster.bpmn.model.SequenceFlow;
import store.lunangangster.engine.impl.Context;
import store.lunangangster.engine.impl.agenda.NodeFlowEngineAgenda;
import store.lunangangster.engine.impl.el.ExpressManager;
import store.lunangangster.engine.impl.entity.ExecutionEntity;
import store.lunangangster.engine.impl.entity.mgr.ExecutionEntityManager;

public class InclusiveGatewayBehavior extends GatewayBehavior {

  private static final Logger log = LoggerFactory.getLogger(InclusiveGatewayBehavior.class);

  @Override
  public void doBehavior(ExecutionEntity execution) {
    InclusiveGateway inclusiveGateway = (InclusiveGateway) execution.getCurrentFlowElement();

    List<SequenceFlow> outgoings = inclusiveGateway.getOutgoing();
    List<SequenceFlow> legalOutgoings = new ArrayList<>(outgoings.size());

    // 计算合适路径
    ExpressManager expressManager = Context.getProcessEngineConfiguration().getExpressManager();
    for (SequenceFlow sequenceFlow : outgoings) {
      String conditionExpression = sequenceFlow.getConditionExpression();
      if (expressManager.evalExpression(conditionExpression, execution)) {
        legalOutgoings.add(sequenceFlow);
      }
    }
    // 选择默认路径
    if (legalOutgoings.isEmpty()) {
      if (inclusiveGateway.getDefaultPath() != null) {
        for (SequenceFlow sequenceFlow : outgoings) {
          if (sequenceFlow.getId().equals(inclusiveGateway.getDefaultPath())) {
            legalOutgoings.add(sequenceFlow);
            log.debug("{}没有合适的出边，选择默认路径: {}", inclusiveGateway, inclusiveGateway.getDefaultPath());
            break;
          }
        }
      }
    }

    // go Next
    NodeFlowEngineAgenda agenda = Context.getCommandContext().getAgenda();
    ExecutionEntityManager executionManager = Context.getProcessEngineConfiguration()
        .getExecutionEntityManager();
    SequenceFlow firstSequenceFLow = legalOutgoings.get(0);
    execution.setCurrentFlowElement(firstSequenceFLow);
    agenda.addDoElementBehaviorOperation(execution, inclusiveGateway);

    for (int i = 1; i < legalOutgoings.size(); i++) {
      ExecutionEntity brotherExecution = executionManager.createBrotherExecution(execution);
      brotherExecution.setCurrentFlowElement(legalOutgoings.get(i));
      agenda.addDoElementBehaviorOperation(brotherExecution, inclusiveGateway);
    }
  }
}
